home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / delivery / deliver.tz / deliver / header.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-07  |  5.3 KB  |  307 lines

  1. /* $Header: header.c,v 2.5 89/11/10 12:23:54 network Exp $
  2.  *
  3.  * A program to parse RFC 822 mail/news headers.
  4.  *
  5.  * usage: header [-c] [-n] [-v] [-f field] ... files
  6.  *
  7.  * Default action is to print entire header.  If one or more -f options
  8.  * are given, only the specified fields are printed.  The field names are
  9.  * not printed unless -n is specified.  Field name comparisons are case
  10.  * insensitive unless -c is specified.  If -v is specified, all headers 
  11.  * except those specified with -f are printed.  NOTE: -v implies -n.
  12.  *
  13.  * Output lines are preceeded by the filename if more than one file is
  14.  * specified.
  15.  *
  16.  * This program is intended for use in delivery files, to extract multi-
  17.  * line header fields.
  18.  *
  19.  * $Log:    header.c,v $
  20.  * Revision 2.5  89/11/10  12:23:54  network
  21.  * Delintify.
  22.  * 
  23.  * Revision 2.4  89/10/30  16:08:48  network
  24.  * Don't automatically print field names with "-v".  (Sorry, Tom.)
  25.  * 
  26.  * Revision 2.3  89/10/30  16:03:29  network
  27.  * Add "-v" (everything except) option.
  28.  * Submitted by Tom Neff <tneff%bfmny0@uunet.uu.net>.
  29.  * 
  30.  * Revision 2.2  89/06/09  13:08:07  network
  31.  * Adapt to BSD quirks.
  32.  * 
  33.  * Revision 2.1  89/06/09  12:25:29  network
  34.  * Update RCS revisions.
  35.  * 
  36.  * Revision 1.5  89/06/09  12:23:51  network
  37.  * Baseline for 2.0 release.
  38.  * 
  39.  */
  40.  
  41. #include <stdio.h>
  42. #include <ctype.h>
  43.  
  44. /*
  45.  * Manifest constants
  46.  */
  47.  
  48. #define TRUE 1
  49. #define FALSE 0
  50.  
  51. /*
  52.  * Other useful macros.
  53.  */
  54.  
  55. #define GETSIZE(buf)    (sizeof(buf) - 1)
  56.  
  57. #define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
  58.         && (p)[3] == 'm' && (p)[4] == ' ')
  59.  
  60. /*
  61.  * External data.
  62.  */
  63.  
  64. /* Variables set by getopt() [blech] */
  65.  
  66. extern  int     optind, opterr;
  67. extern  char    *optarg;
  68.  
  69. /*
  70.  * Library functions.
  71.  */
  72.  
  73. extern  char    *malloc();
  74. extern  char    *realloc();
  75. extern  void    free();
  76.  
  77. /*
  78.  * Global data
  79.  */
  80.  
  81. int     field_count     = 0;
  82. int     field_alloc     = 0;
  83. char    **field_names   = NULL;
  84.  
  85. int     nocasematch     = TRUE;         /* ignore case in header matches */
  86. int     printnames      = FALSE;        /* print field names with data */
  87. int     except          = FALSE;        /* reverse sense of -f */
  88.  
  89. /*----------------------------------------------------------------------
  90.  * The Program.
  91.  */
  92.  
  93. main(argc, argv)
  94. int     argc;
  95. char    **argv;
  96. {
  97.     int     c, errors;
  98.  
  99.     field_alloc = 8;
  100.     field_names = (char **) malloc(field_alloc * sizeof(char **));
  101.     if (field_names == NULL)
  102.         nomem();
  103.  
  104.     errors = FALSE;
  105.     while ((c = getopt(argc, argv, "cnvf:")) != EOF)
  106.     {
  107.         switch (c)
  108.         {
  109.         case 'c':
  110.             nocasematch = FALSE;
  111.             break;
  112.         case 'n':
  113.             printnames = TRUE;
  114.             break;
  115.         case 'v':
  116.             except = TRUE;
  117.             break;
  118.         case 'f':
  119.             if (field_count >= field_alloc)
  120.             {
  121.                 field_alloc *= 2;
  122.                 field_names =
  123.                     (char **) realloc((char *)field_names,
  124.                           field_alloc * sizeof(char **));
  125.                 if (field_names == NULL)
  126.                     nomem();
  127.             }
  128.             field_names[field_count++] = optarg;
  129.             break;
  130.         default:
  131.             errors = TRUE;
  132.             break;
  133.         }
  134.     }
  135.  
  136.     if (errors)
  137.         usage();
  138.  
  139.     if (optind == argc)
  140.         header(stdin, (char *)NULL);
  141.     else
  142.     {
  143.         FILE    *fp;
  144.         int     a, filenames;
  145.  
  146.         filenames = ((argc - optind) > 1);
  147.         for (a = optind; a < argc; ++a)
  148.         {
  149.             if ((fp = fopen(argv[a], "r")) == NULL)
  150.             {
  151.                 errors = TRUE;
  152.                 perror(argv[a]);
  153.                 continue;
  154.             }
  155.  
  156.             header(fp, (filenames ? argv[a] : (char *)NULL));
  157.             (void) fclose(fp);
  158.         }
  159.     }
  160.  
  161.     exit(errors ? 1 : 0);
  162.     /* NOTREACHED */
  163. }
  164.  
  165. usage()
  166. {
  167.     (void) fprintf(stderr,
  168.         "usage: header [-c] [-n] [-v] [-f fieldname] ... files\n");
  169.     exit(1);
  170. }
  171.  
  172. nomem()
  173. {
  174.     (void) fprintf(stderr, "header: out of memory\n");
  175.     exit(1);
  176. }
  177.  
  178. header(fp, filename)
  179. FILE    *fp;
  180. char    *filename;
  181. {
  182.     char    buf[1024];
  183.  
  184.     if (fgets(buf, GETSIZE(buf), fp) == NULL)
  185.         return;
  186.  
  187.     /* Ignore From_ line(s). */
  188.  
  189.     while (ISFROM(buf) || buf[0] == '>')
  190.     {
  191.         if (fgets(buf, GETSIZE(buf), fp) == NULL)
  192.             return;
  193.     }
  194.  
  195.     while (buf[0] != '\n')
  196.     {
  197.         char    *p;
  198.         int     print_this;
  199.  
  200.         p = buf;
  201.         while (isupper(*p) || islower(*p) || isdigit(*p) || *p == '-')
  202.             ++p;
  203.         if (p == buf || *p != ':')
  204.             break;
  205.         print_this = field(buf, p - buf);
  206.         if (except)
  207.             print_this = !print_this;
  208.         if (print_this)
  209.         {
  210.             if (filename)
  211.             {
  212.                 (void) fputs(filename, stdout);
  213.                 (void) fputc(':', stdout);
  214.             }
  215.             ++p;
  216.             if (*p == ' ' || *p == '\t')
  217.                 ++p;
  218.             if (field_count == 0 || printnames)
  219.                 (void) fputs(buf, stdout);
  220.             else
  221.                 (void) fputs(p, stdout);
  222.         }
  223.  
  224.         /* get the next input line */
  225.         if (fgets(buf, GETSIZE(buf), fp) == NULL)
  226.             break;
  227.  
  228.         /* deal with continuation lines */
  229.         while (buf[0] == ' ' || buf[0] == '\t')
  230.         {
  231.             if (print_this)
  232.             {
  233.                 if (filename)
  234.                 {
  235.                     (void) fputs(filename, stdout);
  236.                     (void) fputc(':', stdout);
  237.                 }
  238.                 (void) fputs(buf, stdout);
  239.             }
  240.  
  241.             if (fgets(buf, GETSIZE(buf), fp) == NULL)
  242.             {
  243.                 buf[0] = '\n';
  244.                 break;
  245.             }
  246.         }
  247.     }
  248. }
  249.  
  250. int
  251. field(s, n)
  252. char    *s;
  253. int     n;
  254. {
  255.     int     i;
  256.  
  257.     if (field_count == 0)
  258.         return TRUE;
  259.  
  260.     for (i = 0; i < field_count; ++i)
  261.     {
  262.         char    *f = field_names[i];
  263.  
  264.         if (strlen(f) == n)
  265.         {
  266.             if (nocasematch)
  267.             {
  268.                 if (ci_strncmp(f, s, n) == 0)
  269.                     return TRUE;
  270.             }
  271.             else
  272.             {
  273.                 if (strncmp(f, s, n) == 0)
  274.                     return TRUE;
  275.             }
  276.         }
  277.     }
  278.  
  279.     return FALSE;
  280. }
  281.  
  282. int
  283. ci_strncmp(s, t, n)
  284. char    *s, *t;
  285. int     n;
  286. {
  287.     char    c, d;
  288.  
  289.     while (n-- > 0)
  290.     {
  291.         c = *s++;
  292.         d = *t++;
  293.         if ((c == 0) && (d == 0))
  294.             break;
  295.         if (isupper(c))
  296.             c = tolower(c);
  297.         if (isupper(d))
  298.             d = tolower(d);
  299.         if (c > d)
  300.             return 1;
  301.         if (c < d)
  302.             return -1;
  303.     }
  304.  
  305.     return 0;
  306. }
  307.